#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/11/18 上午8:23
# @Author  : ytq
# @FileName: orderServer.py
# @Software: PyCharm
# @ps :fork from 钱老师

import json

import jsonpath
from flask import Flask, request, make_response, jsonify

app = Flask(__name__)
user_token_dic = {
    'user01': '3b6754f00bb0063071c5b71ce2b56b4ed0ce56a63493e785bea85b74c41ce200'
    , 'user02': 'dcdc7286f6822dc5a4b54d2ce53f40ae0e562d7fc06d64b8dd332f7d528c7c67'
    , 'user03': '04c4fba92b3451b16daedbbc7dd4cec84b8a88333f3da60626c6abbfdc829a02'
    , 'user04': '3c3a7fa64c34e2530b708ec9bdeedd49e0098bfd3239b1cd58985feeb38531b8'
    , 'user05': 'abb9d47918055902a8a6f3f8e86cd962d37d49647e9b51bdd7f7d67ff95f9864'
    , 'user06': '6b2b8f34dd4ad1812a76a7037ed23d9ebc0189070320fa32dc610a79852419c7'
    , 'user07': 'aac287a1eeb39d1983aaa732a7a5f33a64918adb1e88da6b344d2090eaed7239'
    , 'user08': '3d0c7ff2ad3063bc0e93befeef895def90290114ee590ca09b60f8e4476aca27'
    , 'user09': 'a0a9941e29cebdd732a2a57411f14d45e14bc3061d66c2e1c30eca421ed0b02d'
    , 'user10': '34467677a88fc7966807c26ced0972cc775be9e6983d4bfbd2a0981a4350dcfd'
}
menu_json = {
    "code": "200",
    "breakfast": [
        {
            "menu_number": "01",
            "menu_price": 5.50,
            "menu_name": "小笼包"
        },
        {
            "menu_number": "02",
            "menu_price": 3.00,
            "menu_name": "八宝粥"
        },
        {
            "menu_number": "03",
            "menu_price": 1.50,
            "menu_name": "油条"
        },
        {
            "menu_number": "04",
            "menu_price": 1.00,
            "menu_name": "茶叶蛋"
        },
        {
            "menu_number": "05",
            "menu_price": 1.50,
            "menu_name": "豆包"
        },
        {
            "menu_number": "06",
            "menu_price": 2.00,
            "menu_name": "烧饼"
        }
    ],
    "lunch": [
        {
            "menu_number": "07",
            "menu_price": 17.00,
            "menu_name": "宫保鸡丁"
        },
        {
            "menu_number": "08",
            "menu_price": 25.00,
            "menu_name": "锅包肉"
        },
        {
            "menu_number": "09",
            "menu_price": 35.00,
            "menu_name": "糖醋排骨"
        },
        {
            "menu_number": "10",
            "menu_price": 30.00,
            "menu_name": "蒜台炒肉片"
        },
        {
            "menu_number": "11",
            "menu_price": 25.50,
            "menu_name": "酸辣土豆丝"
        },
        {
            "menu_number": "12",
            "menu_price": 32.00,
            "menu_name": "红烧茄子"
        }
    ],
    "dinner": [
        {
            "menu_number": "13",
            "menu_price": 21.00,
            "menu_name": "辣椒炒肉"
        },
        {
            "menu_number": "14",
            "menu_price": 15.00,
            "menu_name": "豌豆肉片汤"
        },
        {
            "menu_number": "15",
            "menu_price": 26.00,
            "menu_name": "原味五花肉卷"
        },
        {
            "menu_number": "16",
            "menu_price": 20.00,
            "menu_name": "醋溜白菜"
        },
        {
            "menu_number": "17",
            "menu_price": 25.50,
            "menu_name": "地三鲜"
        },
        {
            "menu_number": "18",
            "menu_price": 39.00,
            "menu_name": "红烧排骨"
        }
    ]
}

server_internal_error_data = {
    "code": "500",
    "message": "Server internal error."
}


@app.route("/api/v1/user/login", methods=['POST'])
def login():
    """登录接口，输入参数格式：
        "authRequest": {
            "userName": "[username]",
            "password": "[password]"
        }
        :return
        Success : http code 200
        {
            "code": "200",
            "message": "login success",
            "access_token": "3b6754f00bb0063071c5b71ce2b56b4ed0ce56a63493e785bea85b74c41ce200"
        }
        Fail : http code 401
        {
            "code": "401",
            "message": "login fail"
        }
    """
    try:
        raw_data = request.get_data(as_text=True)
        data = json.loads(raw_data)
        username = data.get("authRequest").get("userName")
        password = data.get("authRequest").get("password")
        app.logger.info(f"收到的接口请求中的用户名为{username},密码为{password}")
        if username not in user_token_dic.keys() or password != 'pwd':
            app.logger.error('Username or password error!')
            login_fail_resp_data = {
                "code": "401",
                "message": "login fail"
            }
            app.logger.warning(f"将要返回的数据为{login_fail_resp_data}")
            return make_response(jsonify(login_fail_resp_data), '401')

        login_succ_resp_data = {
            "code": "200",
            "message": "login success",
            "access_token": user_token_dic.get(username)
        }
        app.logger.info(f"将要返回的数据为{login_succ_resp_data}")
        return make_response(jsonify(login_succ_resp_data), '200')
    except Exception as e:
        app.logger.error(f"发生了错误，内容是 {e}")
        app.logger.info(f"将要返回的数据为{server_internal_error_data}")
        return make_response(jsonify(server_internal_error_data), '500')


@app.route('/api/v1/menu/list', methods=['GET'])
def list():
    """菜单浏览接口
    :return: 菜单列表
    """
    access_token = request.headers.get("access_token")
    app.logger.info(f"收到的接口请求中的token为{access_token}")

    if access_token is None:
        login_fail_resp_data = {
            "code": "401",
            "message": "Please login first."
        }
        app.logger.warning(f"将要返回的数据为{login_fail_resp_data}")
        return make_response(jsonify(login_fail_resp_data), '401')

    if access_token not in user_token_dic.values():
        app.logger.error('access_token error, please re-login.')
        login_fail_resp_data = {
            "code": "401",
            "message": "Unknown user info, please re-login."
        }
        app.logger.warning(f"将要返回的数据为{login_fail_resp_data}")
        return make_response(jsonify(login_fail_resp_data), '401')

    category = request.args.get("type")
    app.logger.info(f"收到的接口请求中的type为{category}")
    if category is not None:
        menu_json_dat = menu_json.get(category)
        app.logger.info(f"将要返回的数据为{menu_json_dat}")
        return make_response(jsonify(menu_json_dat), 200)
    app.logger.info(f"将要返回的数据为{menu_json}")
    return make_response(jsonify(menu_json), 200)


@app.route("/api/v1/menu/confirm", methods=['POST'])
def confirm():
    """下单接口，输入参数格式：
        header = {'access_token' : ''}
        data:
        {
            "order_list": [
                {
                    "menu_number" : "01",
                    "number" : 1
                },
                {
                    "menu_number" : "03",
                    "number" : 2
                },
                {
                    "menu_number" : "04",
                    "number" : 1
                },
                {
                    "menu_number" : "05",
                    "number" : 3
                }
            ]
        }
        :return
        Success : http code 200
        {
            "code": "200",
            "message": "Order success.",
            "total": 7
            "total_price": 14.0
        }
        not login : http code 401
        {
            "code": "401",
            "message": "Please login first."
        }
    """
    try:
        access_token = request.headers.get("access_token")
        app.logger.info(f"收到的接口请求中的token为{access_token}")
        if access_token is None:
            login_fail_resp_data = {
                "code": "401",
                "message": "Please login first."
            }
            app.logger.warning(f"将要返回的数据为{login_fail_resp_data}")
            return make_response(jsonify(login_fail_resp_data), '401')

        raw_data = request.get_data(as_text=True)
        order_list = json.loads(raw_data).get("order_list")
        app.logger.info(f"收到的接口请求中的order_list为{order_list}")
        total = 0
        total_price = 0
        for order in order_list:
            total = total + order.get("number")
            menu_number = order.get("menu_number")
            price = jsonpath.jsonpath(menu_json, f"$..[?(@.menu_number=='{menu_number}')]")[0]["menu_price"]
            total_price = total_price + price * order.get("number")

        order_success_resp_data = {
            "code": "200",
            "message": "Order success.",
            "total": total,
            "total_price": total_price
        }
        app.logger.info(f"将要返回的数据为{order_success_resp_data}")
        return make_response(jsonify(order_success_resp_data), '200')
    except Exception as e:
        app.logger.error(f"发生了错误，内容是 {e}")
        app.logger.info(f"将要返回的数据为{server_internal_error_data}")
        return make_response(jsonify(server_internal_error_data), '500')


@app.route("/api/v1/user/logout", methods=['DELETE'])
def logout():
    """用户注销接口，输入参数格式：
        header = {'access_token' : ''}
        此接口仅用于测试是否登录后再调用退出，不会注销token
    """
    try:
        access_token = request.headers.get("access_token")
        app.logger.info(f"收到的接口请求中的token为{access_token}")

        if access_token not in user_token_dic.values():
            app.logger.error('access_token error, logout failed.')
            login_fail_resp_data = {
                "code": "401",
                "message": "Unknown user info, logout fail."
            }
            app.logger.warning(f"将要返回的数据为{login_fail_resp_data}")
            return make_response(jsonify(login_fail_resp_data), '401')

        logout_succ_resp_data = {
            "code": "200",
            "message": "logout success"
        }
        app.logger.info(f"将要返回的数据为{logout_succ_resp_data}")
        return make_response(jsonify(logout_succ_resp_data), '200')
    except Exception as e:
        app.logger.error(f"发生了错误，内容是 {e}")
        app.logger.info(f"将要返回的数据为{server_internal_error_data}")
        return make_response(jsonify(server_internal_error_data), '500')


if __name__ == "__main__":
    # 启动服务
    app.run(port=9091, debug=True, host='0.0.0.0')
